/* ----------------------------------------------------------------------------
* File: chat_info_module_impl.cpp
*
* Desc: Module for getting chat info - definition
*
* Created: 24/05/2011, by Alexey Korshunov
* ---------------------------------------------------------------------------- */
#include "chat_info_module_impl.h"


namespace ModuleManagement
{
	std::auto_ptr<Module> CreateChatInfoModule(const ChatInfoModuleParams& params)
	{
		std::auto_ptr<Module> module;
		try
		{
			// Create object
			std::auto_ptr<ModuleChatInfoImpl> obj(new ModuleChatInfoImpl());

			// Init
			obj->Init(params);

			module = obj;
		}
		catch(Common::Exception& e)
		{
		}

		return module;
	}
}


namespace ModuleManagement
{
	ModuleChatInfoImpl::ModuleChatInfoImpl() throw(Common::Exception)
		: m_Thread(NULL)
		, StartEvent(NULL)
		, StopEvent(NULL)
		, m_SkypeInstance(NULL)
	{
		CreateSyncObjects();
	}

	ModuleChatInfoImpl::~ModuleChatInfoImpl()
	{
		StopThread();
		DestroySyncObjects();
	}

	void ModuleChatInfoImpl::Init(const ChatInfoModuleParams& params) throw(Common::Exception)
	{
		{
			using namespace SkypeProxyManagement;

			SkypeProxyParams proxyParams;
			proxyParams.AttachWaitTime = 300;	// ms

			m_SkypeProxy = CreateSkypeProxy(proxyParams);
			if (!m_SkypeProxy.get())
			{
#ifdef _DEBUG
				MyOutputDebugString("ModuleChatInfo: ERROR - Unable to create instance manager");
#endif
				throw Common::Exception("ModuleChatInfo - Unable to create instance manager");
			}

			m_SkypeInstance = m_SkypeProxy->GetSkypeInstance();

#ifdef _DEBUG
			MyOutputDebugString("ModuleChatInfo: Instance manager - OK");
#endif
		}
	}

	Common::Error ModuleChatInfoImpl::Start(void* param, size_t size)
	{
		// Create main thread
		DWORD dwThreadId;
		m_Thread = CreateThread(NULL, 0, ThreadFunc, (LPVOID)this, 0, &dwThreadId);
		if (m_Thread == NULL)
			return Common::SKYPE_ERROR;
		
		// Wait start thread
		WaitForSingleObject(StartEvent, INFINITE);

		return Common::SKYPE_SUCCESS;
	}

	Common::Error ModuleChatInfoImpl::Stop(void* param, size_t size)
	{
		StopThread();
		return Common::SKYPE_SUCCESS;
	}

	DWORD WINAPI ModuleChatInfoImpl::ThreadFunc(LPVOID param)
	{
		SKYPE4COMLib::IChatPtr Chat = NULL;

		ModuleChatInfoImpl* module = reinterpret_cast<ModuleChatInfoImpl*>(param);
		if (module == NULL)
			ExitThread(0);

		try
		{
			// Display chat names
			if (module->DisplayChatNames() != Common::SKYPE_SUCCESS)
				throw Common::Exception("Error while display chat names");

			// Detect necessary chat
			if ((Chat = module->DetectChat()) == NULL)
				throw Common::Exception("Unable to detect chat");
			
			// Read all messages from chat
			/*if (ReadMessages(&pSkypeEnv->chatInfo) != SKYPE_PLUG_OK)
			{
				pSkypeEnv->bError = true;
				CoUninitialize();
				ExitThread(0);
			}*/
		}
		catch(const Common::Exception& e)
		{
			MyOutputDebugString("Exception: %s", e.GetStr().c_str());
		}
		catch(...)
		{
			MyOutputDebugString("Unexpected exception");
		}

		ExitThread(0);
	}

	/************************************************************************/
	/* Display names of all chats                                           */
	/************************************************************************/
	Common::Error ModuleChatInfoImpl::DisplayChatNames()
	{
		MyOutputDebugString("ModuleChatInfo: Chat names:");

		// Display all chat names
		SKYPE4COMLib::IChatCollectionPtr ChatCollection = m_SkypeInstance->GetChats();
		long Count = ChatCollection->GetCount();
		MyOutputDebugString("ModuleChatInfo: Chats count - %d", Count);

		for (long i = 1; i <= Count; ++i)
		{
			_bstr_t Name = ChatCollection->GetItem(i)->GetName();
			MyOutputDebugString("ModuleChatInfo: %s", (LPCSTR)Name);
		}

		ChatCollection = NULL;
		return Common::SKYPE_SUCCESS;
	}

	/************************************************************************/
	/* Detect necessary chat                                                */
	/************************************************************************/
	SKYPE4COMLib::IChatPtr ModuleChatInfoImpl::DetectChat()
	{
		SKYPE4COMLib::IChatPtr pChat = NULL;

		SKYPE4COMLib::IChatCollectionPtr ChatCollection = m_SkypeInstance->GetChats();
		long Count = ChatCollection->GetCount();
		MyOutputDebugString("ModuleChatInfo: Chats count - %d", Count);

		for (long i = 1; i <= Count; ++i)
		{
			if (IsNecessaryChat(ChatCollection->GetItem(i)))
			{
				pChat = ChatCollection->GetItem(i);
				break;
			}
		}

		ChatCollection = NULL;
		return pChat;
	}

	/************************************************************************/
	/* Detect our chat                                                      */
	/************************************************************************/
	bool ModuleChatInfoImpl::IsNecessaryChat(SKYPE4COMLib::IChatPtr Chat)
	{
		bool res = false;

		SKYPE4COMLib::IUserCollectionPtr UserCollection = Chat->GetMembers();
		long Count = UserCollection->GetCount();

		MyOutputDebugString("SkypePlugin: Chat name - %s, members - %d, messages - %d", (LPCTSTR)Chat->GetFriendlyName(), Count, Chat->GetMessages()->GetCount());

		// Condition
		if (Count > 10)
			res = true;

		UserCollection = NULL;
		return res;
	}


	/************************************************************************/
	/* Create internal sync objects                                         */
	/************************************************************************/
	void ModuleChatInfoImpl::CreateSyncObjects() throw(Common::Exception)
	{
		StartEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
		if (StartEvent == NULL)
			throw Common::Exception("ModuleChatInfo - Unable to create event object");

		StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
		if (StopEvent == NULL)
			throw Common::Exception("ModuleChatInfo - Unable to create event object");
	}

	/************************************************************************/
	/* Destroy internal sync objects                                        */
	/************************************************************************/
	void ModuleChatInfoImpl::DestroySyncObjects()
	{
		CloseHandle(StartEvent);
		CloseHandle(StopEvent);
	}

	/************************************************************************/
	/* Stop main thread														*/
	/************************************************************************/
	void ModuleChatInfoImpl::StopThread()
	{
		SetEvent(StopEvent);
		WaitForSingleObject(m_Thread, INFINITE);
		CloseHandle(m_Thread);
	}
}


